package com.sunxueqi.framework.security.service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.sunxueqi.common.constant.CfnConstants;
import com.sunxueqi.framework.redis.RedisCacheService;
import com.sunxueqi.framework.security.LoginUser;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class TokenService {
	/**
	 * 密钥
	 */
	@Value("${token.secret}")
	private String secret;
	
	/**
	 * 有效期
	 */
	@Value("${token.expireTime}")
	private int expireTime;
	
	protected static final long MILLIS_SECOND = 1000;
	protected static final long MOLLIS_MINUTE = 60 * MILLIS_SECOND;
	protected static final Long MILLIS_MINUTE_TEN = 10 * 60 * 1000L;
	
	@Autowired
	private RedisCacheService redisCacheService;

	/**
	 * 为登录用户创建token信息
	 * 
	 * @param loginUser
	 * @return
	 */
	public String createToken(LoginUser loginUser) {
		String token = IdUtil.simpleUUID();
		loginUser.setToken(token);
		// setUserAgent(loginUser);
		refreshToken(loginUser);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put(CfnConstants.LOGIN_USER_KEY, token);
		return createToken(map);
	}

	public String createToken(Map<String, Object> claims) {
		return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, secret).compact();
	}

	/**
	 * 获取当前登录用户信息
	 * 
	 * @param request
	 * @return
	 */
	public LoginUser getLoginUser(HttpServletRequest request) {
		String token = getToken(request);
		if (StrUtil.isNotBlank(token)) {
			Claims claims = parseToken(token);
			String uuid = (String) claims.get(CfnConstants.LOGIN_USER_KEY);
			String userKey = getTokenKey(uuid);
			return redisCacheService.getCacheObject(userKey);
		}
		return null;
	}

	private Claims parseToken(String token) {
		return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
	}

	private String getTokenKey(String uuid) {
		return CfnConstants.LOGIN_USER_KEY + uuid;
	}

	/**
	 * 获取请求的token。如果参数中取不到就到Header里去取
	 * 
	 * @param request
	 * @return 请求的token
	 */
	private String getToken(HttpServletRequest request) {
		String token = request.getHeader(CfnConstants.TOKEN);
		if (StrUtil.isBlank(token)) {
			token = request.getHeader(CfnConstants.TOKEN);
		}
		return token;
	}

	/**
	 * 验证token有效期，相差不足20分钟，则自动刷新
	 * 
	 * @param loginUser
	 */
	public void verifyToken(LoginUser loginUser) {
		long expireTime = loginUser.getExpireTime();
		long currentTime = System.currentTimeMillis();
		if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
			refreshToken(loginUser);
		}
	}

	/**
	 * 刷新token的有效期
	 * 
	 * @param loginUser
	 */
	public void refreshToken(LoginUser loginUser) {
		loginUser.setLoginTime(System.currentTimeMillis());
		loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MOLLIS_MINUTE);
		String userKey = getTokenKey(loginUser.getToken());
		redisCacheService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
	}
	
	/**
	 * 删除登录用户的身份信息
	 * @param token
	 */
	public void deleteLoginUser(String token) {
		if(StrUtil.isNotBlank(token)) {
			String userKey = getTokenKey(token);
			redisCacheService.deleteObject(userKey);
		}
	}
}
